package com.example.interactservice.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.commom.enums.RespDescEnum;
import com.example.commom.enums.StatusCodeEnum;
import com.example.commom.global.KafkaConstants;
import com.example.commom.global.RedisConstants;
import com.example.commom.utils.KafkaUtils;
import com.example.feign.client.UserClient;
import com.example.feign.result.AjaxResult;
import com.example.interactservice.entity.Follow;
import com.example.interactservice.mapper.FollowMapper;
import com.example.interactservice.service.FollowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 软工2104-李家强-2100770248
 * @since 2023-09-27
 */
@Transactional
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements FollowService {

    @Autowired
    private UserClient userClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private KafkaUtils kafkaUtils;

    /**
     *  用户关注/取关
     * @param followUserId 关注/取关的目标用户id
     * @param isFollow true: 关注, false: 取关
     * @param userId 登录的用户id
     * @return 返回结果
     */
    @Override
    public AjaxResult follow(Long followUserId, boolean isFollow, String userId) {

        // 自己可不能关注/取关自己!
        if (userId.equals(followUserId+"")) {
            return AjaxResult.fail(RespDescEnum.MissRequiredParameter.getValue());
        }

        // 判断关注/取关的用户id是否合法
        boolean isExist = userClient.userIsExist(followUserId);
        if (!isExist) {
            return AjaxResult.fail(RespDescEnum.MissRequiredParameter.getValue());
        }

        // 构造实体类
        Follow follow = new Follow();
        follow.setFollowId(null);
        follow.setFollowUserId(followUserId);
        follow.setUserId(Long.parseLong(userId));

        boolean success;
        String key = RedisConstants.REDIS_FOLLOW_PRE_KRY + userId;

        // 先查询出是否有记录
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, followUserId + "");


        if (isFollow) {
            // 已经关注了
            if (Boolean.TRUE.equals(isMember)) {
                return AjaxResult.success(StatusCodeEnum.OK.getMsg());
            }

            success = save(follow);
            if (success) {
                // 将关注用户的id 放到 redis 集合中
                stringRedisTemplate.opsForSet().add(key, followUserId+"");
            }

        } else {
            // 并没有关注
            if (Boolean.FALSE.equals(isMember)) {
                return AjaxResult.success(StatusCodeEnum.OK.getMsg());
            }

            LambdaQueryWrapper<Follow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Follow::getFollowUserId, follow.getFollowUserId())
                    .eq(Follow::getUserId, follow.getUserId());
            // 删除数据
            success = remove(lambdaQueryWrapper);
            if (success) {
                // 将关注用户的id 从 redis 集合移除
                stringRedisTemplate.opsForSet().remove(key, followUserId+"");
            }
        }

        if (!success) {
            return AjaxResult.fail(StatusCodeEnum.FAILED.getMsg());
        }

        // 向kafka 推送消息
        kafkaUtils.sendKafkaMessageWithRetry(KafkaConstants.KAFKA_USER_FOLLOW_TOPIC, KafkaConstants.KAFKA_USER_FOLLOW_TOPIC,
                (followUserId+ ":" + isFollow + ":" + userId).getBytes(StandardCharsets.UTF_8));
        return AjaxResult.success(StatusCodeEnum.OK.getMsg());
    }


    /**
     *  查看是否关注了指定用户
     * @param followUserId 目标用户id
     * @param userId  登录用户 id
     * @return true: 已关注, false: 未关注
     */
    @Override
    public AjaxResult isFollow(String followUserId, String userId) {
        // 查询是否存在记录即可

        LambdaQueryWrapper<Follow> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Follow::getUserId, userId)
                .eq(Follow::getFollowUserId, followUserId);

        Follow follow = getOne(lambdaQueryWrapper);

        // 不为空就是关注了.
        return AjaxResult.success(follow != null);
    }

}
